package cn.wuyi.common.rest;


import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestTemplate;

/**
 * 
 * @类功能说明:  采用Spring RestTemplate 实现rest客户端 
 * @公司名称     :中企动力
 * @作者                ：ce 
 * @创建时间      ：2015年8月28日 上午10:55:15  
 * @版本                ：V1.0
 */
public class RESTClientImpl implements RESTClient {

	private Logger logger = LoggerFactory.getLogger(this.getClass());
	
	public ResponseResult<String> doHttpRequest(String url, String method,Object requestBody, Map<String, String> header,Map<String, ?> parameter) {
		ResponseResult<String> result = new ResponseResult<String>();
		//开始时间
		long startTime = System.currentTimeMillis();
		//请求方法
		HttpMethod httpMethod = this.getHttpMethod(method);
		//请求URL
		String requestUrl = url;
		//请求参数处理成key={key}的形式追加在url后面
		if(parameter != null && parameter.size() > 0){
			RestUrl restUrl = new RestUrl(url);
			requestUrl = restUrl.putParameter(parameter).getUrl();
		}else{
			parameter = new HashMap<String,Object>();
		}
		//请求头
		HttpHeaders httpHeaders = new HttpHeaders();
		if(header != null && header.size() > 0){
			httpHeaders.setAll(header);
		}
		HttpEntity<Object> entity = new HttpEntity<Object>(requestBody,httpHeaders);	
		ResponseEntity<String> response = null;
		try{
			response = RestTemplateHolder.getTemplateByActionUrl(requestUrl).exchange(requestUrl, httpMethod, entity, String.class, parameter);
			//清理当前线程存放RestTemplateExt对象中的属性,使其恢复默认值,防止影响其他方法调用
			//原因：每次从当前线程获取RestTemplate发送http请求结束后,并不需要清理当前线程的RestTemplate对象,但需要清理该RestTemplate对象的属性
			RestTemplateHolder.cleanTemplateAttr();
			
			result.setCode(response.getStatusCode().value());
			result.setBody(response.getBody());
			result.setResultDesc(response.getStatusCode().getReasonPhrase());
		}catch(Exception ex){
			if(response != null){
				result.setCode(response.getStatusCode().value());
				result.setBody(response.getBody());
				result.setResultDesc(response.getStatusCode().getReasonPhrase());
			}else{
				result.setCode(ResponseResult.EXCEPTION_CODE);
				result.setResultDesc(ResponseResult.EXCEPTION_DESC);
				StackTraceElement [] stacks = ex.getStackTrace();
				StringBuilder sb = new StringBuilder();
				sb.append(ex.getClass().getName()).append(":").append(ex.getMessage()).append("\r\n");
				for(StackTraceElement stack : stacks){
					sb.append(stack.toString()).append("\r\n");
				}
				result.setException(sb.toString());
			}
			ex.printStackTrace();
		}
		logger.info("##调用url:{}响应时间为:{}毫秒",requestUrl,System.currentTimeMillis() - startTime);
		return result;
	}
	
	private HttpMethod getHttpMethod(String method){
		if(StringUtils.isEmpty(method)){
			return HttpMethod.POST;
		}
		HttpMethod [] methods = HttpMethod.values();
		for(HttpMethod m : methods){
			if(m.toString().equals(method.toUpperCase())){
				return m;
			}
		}
		throw new IllegalStateException("Unsupported request method ["+method+"]");
	}
	
	/**
	 * 
	 * @方法功能说明：PUT request ,refresh cache
	 * @作者        : ce
	 * @创建时间    ：2015年8月27日 下午5:06:36 
	 * @param url 请求URL
	 * @param requestBody 请求体
	 * @param header 请求头域信息
	 * @param parameter 路径参数值
	 * @return 响应信息
	 * <p>RestUrl url 的组合方式, for examaple :
	 * <pre>
	 * 
	 * 		RestUrl url = new RestUrl("http://foreman.xcm.cn/api");
	 *      url.put("hosts").put("{pagecache-img01.xcm.cn}").put("puppetrun");
	 *      String URL = url.getUrl();
	 *      组合后的URL为：url = http://foreman.xcm.cn/api/hosts/{pagecache-img01.xcm.cn}/puppetrun
	 *      路径参数parameter,设值方法： parameter.put("pagecache-img01.xcm.cn","pagecache-img01.xcm.cn");
	 *      其中：
	 *      路径中的{}中的占位符名字可以随便取，该值与parameter中的key对应
	 * </pre>
	 */
	public ResponseResult<String> putForObject(String url,Object requestBody,Map<String,String> header,Map<String,?> parameter){
		return this.doHttpRequest(url, "PUT", requestBody, header, parameter);
	}
	
	/**
	 * 
	 * @方法功能说明：GET request 
	 * @作者        : ce
	 * @创建时间    ：2015年8月27日 下午5:06:36 
	 * @param url 请求URL
	 * @param requestBody 请求体
	 * @param header 请求头域信息
	 * @param parameter 路径参数值
	 * @return 响应信息
	 * <p>RestUrl url 的组合方式, for examaple :
	 * <pre>
	 * 
	 * 		RestUrl url = new RestUrl("http://foreman.xcm.cn/api");
	 *      url.put("hosts").put("{pagecache-img01.xcm.cn}").put("puppetrun");
	 *      String URL = url.getUrl();
	 *      组合后的URL为：url = http://foreman.xcm.cn/api/hosts/{pagecache-img01.xcm.cn}/puppetrun
	 *      路径参数parameter,设值方法： parameter.put("pagecache-img01.xcm.cn","pagecache-img01.xcm.cn");
	 *      其中：
	 *      路径中的{}中的占位符名字可以随便取，该值与parameter中的key对应
	 * </pre>
	 */
	public ResponseResult<String> getForObject(String url,Object requestBody,Map<String,String> header,Map<String,?> parameter){
		return this.doHttpRequest(url, "GET", requestBody, header, parameter);
	}
	
	/**
	 * 
	 * @方法功能说明：post request ,refresh cache
	 * @作者        : ce
	 * @创建时间    ：2015年8月27日 下午5:06:36 
	 * @param url 请求URL
	 * @param requestBody 请求体
	 * @param header 请求头域信息
	 * @param parameter 路径参数值
	 * @return 响应信息
	 * <p>RestUrl url 的组合方式, for examaple :
	 * <pre>
	 * 
	 * 		RestUrl url = new RestUrl("http://foreman.xcm.cn/api");
	 *      url.put("hosts").put("{pagecache-img01.xcm.cn}").put("puppetrun");
	 *      String URL = url.getUrl();
	 *      组合后的URL为：url = http://foreman.xcm.cn/api/hosts/{pagecache-img01.xcm.cn}/puppetrun
	 *      路径参数parameter,设值方法： parameter.put("pagecache-img01.xcm.cn","pagecache-img01.xcm.cn");
	 *      其中：
	 *      路径中的{}中的占位符名字可以随便取，该值与parameter中的key对应
	 * </pre>
	 */
	public ResponseResult<String> postForObject(String url,Object requestBody,Map<String,String> header,Map<String,?> parameter){
		return this.doHttpRequest(url, "POST", requestBody, header, parameter);
	}
	
	/**
	 * 
	 * @方法功能说明：Delete request
	 * @作者        : ce
	 * @创建时间    ：2015年8月27日 上午9:38:54 
	 * @param url
	 * @param requestBody
	 * @param header
	 * @param parameter
	 * @return
	 */
	public ResponseResult<String> deleteForObject(String url,Object requestBody,Map<String,String> header,Map<String,?> parameter){
		return this.doHttpRequest(url, "DELETE", requestBody, header, parameter);
	}
	
	/*
     *初始化RestTemplate，RestTemplate会默认添加HttpMessageConverter
     * 添加的StringHttpMessageConverter非UTF-8
     * 所以先要移除原有的StringHttpMessageConverter，
     * 再添加一个字符集为UTF-8的StringHttpMessageConvert
     * */
    @SuppressWarnings("unused")
	private  void resetStringMessageConverter(RestTemplate restTemplate) {
        List<HttpMessageConverter<?>> converterList = restTemplate.getMessageConverters();
        HttpMessageConverter<?> converterTarget = null;
        for (HttpMessageConverter<?> item : converterList) {
            if (item.getClass() == StringHttpMessageConverter.class) {
                converterTarget = item;
                break;
            }
        }
        if (converterTarget != null) {
            converterList.remove(converterTarget);
        }
        HttpMessageConverter<?> converter = new StringHttpMessageConverter(StandardCharsets.UTF_8);
        converterList.add(converter);
    }



}
